/**
 * 系统日志控制器
 */

import { Context } from 'elysia';
import { eq, desc, and, gte, lte, like, count } from 'drizzle-orm';
import { db } from '../db';
import { systemLogs } from '../db/schema';
import { successResponse, paginatedResponse, errorResponse, createPaginationMeta, asyncHandler, ApiError } from '../utils/response';
import { Logger } from '../utils/response';
import type { AuthContext } from '../middleware/auth';

/**
 * 检查只读访问权限
 */
function checkReadOnlyAccess(context: AuthContext, action: string) {
  if (context.user?.role !== 'admin') {
    throw ApiError.forbidden(`只有管理员可以执行${action}操作`);
  }
}

/**
 * 获取系统日志列表
 */
export const getLogs = asyncHandler(async (context: AuthContext) => {
  const { page = '1', limit = '20', level, module, action, startDate, endDate, search } = context.query as any;
  
  const pageNum = parseInt(page);
  const limitNum = parseInt(limit);
  const offset = (pageNum - 1) * limitNum;
  
  // 构建查询条件
  const conditions = [];
  
  if (level) {
    conditions.push(eq(systemLogs.level, level));
  }
  
  if (module) {
    conditions.push(eq(systemLogs.module, module));
  }
  
  if (action) {
    conditions.push(like(systemLogs.action, `%${action}%`));
  }
  
  if (startDate) {
    conditions.push(gte(systemLogs.createdAt, new Date(startDate)));
  }
  
  if (endDate) {
    conditions.push(lte(systemLogs.createdAt, new Date(endDate)));
  }
  
  if (search) {
    conditions.push(like(systemLogs.message, `%${search}%`));
  }
  
  const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
  
  // 获取总数
  const [{ total }] = await db
    .select({ total: count() })
    .from(systemLogs)
    .where(whereClause);
  
  // 获取日志列表
  const logs = await db
    .select()
    .from(systemLogs)
    .where(whereClause)
    .orderBy(desc(systemLogs.createdAt))
    .limit(limitNum)
    .offset(offset);
  
  const pagination = createPaginationMeta(total, pageNum, limitNum);
  
  Logger.info('获取系统日志列表', {
    total,
    page: pageNum,
    limit: limitNum,
    filters: { level, module, action, startDate, endDate, search }
  });
  
  return paginatedResponse(logs, pagination, '获取系统日志列表成功');
});

/**
 * 获取日志统计信息
 */
export const getLogStats = asyncHandler(async (context: AuthContext) => {
  const { days = '7' } = context.query as any;
  const daysNum = parseInt(days);
  const startDate = new Date();
  startDate.setDate(startDate.getDate() - daysNum);
  
  // 按级别统计
  const levelStats = await db
    .select({
      level: systemLogs.level,
      count: count()
    })
    .from(systemLogs)
    .where(gte(systemLogs.createdAt, startDate))
    .groupBy(systemLogs.level);
  
  // 按模块统计
  const moduleStats = await db
    .select({
      module: systemLogs.module,
      count: count()
    })
    .from(systemLogs)
    .where(gte(systemLogs.createdAt, startDate))
    .groupBy(systemLogs.module)
    .limit(10);
  
  // 总数统计
  const [{ total }] = await db
    .select({ total: count() })
    .from(systemLogs)
    .where(gte(systemLogs.createdAt, startDate));
  
  // 错误日志数量
  const [{ errorCount }] = await db
    .select({ errorCount: count() })
    .from(systemLogs)
    .where(and(
      gte(systemLogs.createdAt, startDate),
      eq(systemLogs.level, 'error')
    ));
  
  const stats = {
    total,
    errorCount,
    levelStats: levelStats.reduce((acc, item) => {
      acc[item.level] = item.count;
      return acc;
    }, {} as Record<string, number>),
    moduleStats: moduleStats.reduce((acc, item) => {
      acc[item.module] = item.count;
      return acc;
    }, {} as Record<string, number>)
  };
  
  Logger.info('获取日志统计信息', { days: daysNum, stats });
  
  return successResponse(stats, '获取日志统计信息成功');
});

/**
 * 清理过期日志
 */
export const cleanupLogs = asyncHandler(async (context: AuthContext) => {
  // 检查管理员权限
  checkReadOnlyAccess(context, '清理日志');
  
  const { days = '30' } = context.body as any;
  const daysNum = parseInt(days);
  
  if (isNaN(daysNum) || daysNum < 1) {
    throw ApiError.validation('天数必须是大于0的数字');
  }
  
  const cutoffDate = new Date();
  cutoffDate.setDate(cutoffDate.getDate() - daysNum);
  
  // 删除过期日志
  const result = await db
    .delete(systemLogs)
    .where(lte(systemLogs.createdAt, cutoffDate));
  
  Logger.info('清理过期日志', {
    days: daysNum,
    cutoffDate,
    deletedCount: result.rowsAffected || 0
  });
  
  return successResponse(
    { deletedCount: result.rowsAffected || 0 },
    `成功清理 ${daysNum} 天前的日志`
  );
});

/**
 * 导出日志
 */
export const exportLogs = asyncHandler(async (context: AuthContext) => {
  // 检查管理员权限
  checkReadOnlyAccess(context, '导出日志');
  
  const { startDate, endDate, level, module } = context.query as any;
  
  // 构建查询条件
  const conditions = [];
  
  if (level) {
    conditions.push(eq(systemLogs.level, level));
  }
  
  if (module) {
    conditions.push(eq(systemLogs.module, module));
  }
  
  if (startDate) {
    conditions.push(gte(systemLogs.createdAt, new Date(startDate)));
  }
  
  if (endDate) {
    conditions.push(lte(systemLogs.createdAt, new Date(endDate)));
  }
  
  const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
  
  // 获取日志数据
  const logs = await db
    .select()
    .from(systemLogs)
    .where(whereClause)
    .orderBy(desc(systemLogs.createdAt))
    .limit(10000); // 限制导出数量
  
  // 转换为CSV格式
  const csvHeader = 'ID,Level,Module,Action,Message,User ID,IP,Request ID,Duration,Created At\n';
  const csvData = logs.map(log => {
    const fields = [
      log.id,
      log.level,
      log.module,
      log.action || '',
      `"${(log.message || '').replace(/"/g, '""')}"`,
      log.userId || '',
      log.ip || '',
      log.requestId || '',
      log.duration || '',
      log.createdAt.toISOString()
    ];
    return fields.join(',');
  }).join('\n');
  
  const csvContent = csvHeader + csvData;
  
  Logger.info('导出日志', {
    count: logs.length,
    filters: { startDate, endDate, level, module }
  });
  
  // 设置响应头
  context.set.headers['Content-Type'] = 'text/csv';
  context.set.headers['Content-Disposition'] = `attachment; filename="system_logs_${new Date().toISOString().split('T')[0]}.csv"`;
  
  return csvContent;
});